home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / vr / vr.c < prev    next >
Text File  |  1994-04-13  |  22KB  |  1,027 lines

  1. /*
  2. ** Raster Virtual Kernel
  3. */
  4.  
  5. #ifdef MPW
  6. #pragma segment ICR
  7. #endif
  8.  
  9. #define MASTERDEF
  10.  
  11. #include "TelnetHeader.h"
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15.  
  16. #include "vr.h"
  17. #include "vr.proto.h"
  18. #include "vrrgmac.proto.h"
  19.  
  20. /*    defines for raster states and variables */
  21.  
  22. /*    states    */
  23. #define    DONE        0        /* we've been called */
  24. #define    ESCFOUND    1        /* found escape */
  25. #define    WANTCMD        2        /* want a command char */
  26. #define    WANTDEL        3        /* want that first delimiter */
  27. #define    IARG        4        /* looking for integer arg */
  28. #define    SARG        5        /* looking for string arg */
  29. #define    CARG        6        /* looking for count arg */
  30. #define    DATA        7        /* all args parsed, found ^ */
  31.  
  32. /*    commands */
  33. #define ESC        0x1b            /* start of a sequence */
  34. #define    ESCCMD    ' '                /* escape to next level of commands */
  35. #define    DELIM    ';'                /* argument delimiter */
  36. #define    CMDTRM    '^'                /* terminator, but also prefix w/ ESC */
  37. #define    WINCMD    'W'                /* create a window */
  38. #define    DESCMD    'D'                /* destroy a window */
  39. #define    MAPCMD    'M'                /* change color map entries */
  40. #define    RLECMD    'R'                /* run-length encoded data */
  41. #define    PIXCMD    'P'                /* standard pixel data */
  42. #define IMPCMD  'I'             /* IMCOMP compressed data */
  43. #define    FILCMD    'F'                /* save to file command */
  44. #define    CLKCMD    'C'                /* click the slide camera */
  45. #define    SAVCMD    'S'                /* save a color map to a file */
  46.  
  47. /*    command parameter types*/
  48. #define    MAXARGS    7                /* maximum args to a command */
  49. #define INT        1                /* integer argument */
  50. #define    STRING    2                /* string (character) argument */
  51. #define    COUNT    3                /* data count argument */
  52. #define LINEMAX 1024            /* longest width for window */
  53.  
  54. /*
  55. ** flag values
  56. */
  57.  
  58. #define FL_NORMAL    1        /* command needs no data */
  59. #define    FL_DATA        2        /* command takes data */
  60.  
  61. /*
  62. ** structure of command table
  63. */
  64.  
  65. struct cmd {
  66.     char    c_name;
  67.     short    c_flags;
  68.     short    (*c_func)(union arg av[], char *);
  69.     short    c_args[MAXARGS];
  70. };
  71.  
  72. struct cmd cmdtab[] = {
  73.     WINCMD, FL_NORMAL, VRwindow, {INT, INT, INT, INT, INT, STRING, 0},
  74.     DESCMD, FL_NORMAL, VRdestroy, {STRING, 0, 0, 0, 0, 0, 0},
  75.     MAPCMD, FL_DATA, VRmap, {INT, INT, COUNT, STRING, 0, 0, 0},
  76.     FILCMD, FL_NORMAL, VRfile, {INT, INT, INT, INT, INT, STRING, STRING},
  77.     PIXCMD, FL_DATA, VRpixel, {INT, INT, INT, COUNT, STRING, 0, 0},
  78.     RLECMD, FL_DATA, VRrle, {INT, INT, INT, COUNT, STRING, 0, 0},
  79.     IMPCMD, FL_DATA, VRimp, {INT, INT, INT, COUNT, STRING, 0, 0},
  80.     CLKCMD, FL_NORMAL, VRclick, {STRING, 0, 0, 0, 0, 0, 0},
  81.     SAVCMD, FL_NORMAL, VRmsave, {STRING, STRING, 0, 0, 0, 0, 0}
  82. };
  83.  
  84. #define NCMDS    (sizeof(cmdtab) / sizeof(struct cmd))
  85.  
  86. /*
  87. ** global vars
  88. */
  89.  
  90. static short            VRstate = DONE;        /* current state */
  91. static short            VRcmdnum = -1;        /* current command */
  92. static short            VRargcount = 0;        /* number of args for command */
  93. static short            VRdatalen = 0;        /* length of expected data */
  94. static short            VRbufpos = 0;        /* current pointer in tempdata */
  95. static union arg    VRargs[MAXARGS];    /* argument vector */
  96. static char            VRtempdata[256];    /* temporary storage while parsing */
  97. static char         *VRspace;            /* storage for incoming data */
  98. static char         *VRsp2;                /* storage for pixel expansion */
  99. static char            *VRptr;                /* pointer for data buffer */
  100. static char            *VRptr2;            /* copy of above */
  101.  
  102. /***********************************************************************/
  103. /* decode0 and decode1
  104. *  start and continue the decoding.
  105. *
  106. *  Returns real characters, 0 if in the middle of an escape sequence.
  107. */
  108.  
  109. #define FRSKIP 0
  110. #define FRIN 1
  111. #define FRSPECIAL 2
  112. #define FROVER 3
  113. #define FRDONE 4
  114.  
  115. void    ICRunload(void)    {}
  116.  
  117. static short VRnextargstate(short ac, short c);
  118.  
  119. /*
  120. ** VRinit    -- initialize the VR system
  121. **
  122. ** Arguments:
  123. **
  124. **    None.
  125. **
  126. ** Returns:
  127. **
  128. **    short        -- status, 1 == succsessful, 0 == failed
  129. */
  130.  
  131. short    VRinit( void)
  132. {
  133.     VRhead.w_next = NULL;
  134.     VRsp2 = (char *)NewPtr(4*LINEMAX+10);
  135.     VRspace = (char *)NewPtr(LINEMAX+10);
  136.  
  137.     if (VRspace)
  138.         return 1;
  139.     else
  140.         return 0;
  141. }
  142.  
  143. /*
  144. ** VRwrite -- parse a string of VR commands
  145. ** 
  146. ** Arguments:
  147. **
  148. **    char *b;    -- buffer pointer
  149. **    short    len;    -- buffer length
  150. **
  151. ** Returns:
  152. **
  153. **    short            -- Number of characters processed.  0 tells
  154. **                -- the upper level to switch out of raster mode;
  155. **                -- usually on error, but also at completion of
  156. **                -- command processing.
  157. **
  158. */
  159.  
  160. short    VRwrite( char *b, short len)
  161. {
  162.     short        count = 0;
  163.     char        *p = b;
  164.     char        c;
  165.     short        i;
  166.  
  167.     /*    loop 'til no more chars */
  168.  
  169.     while (count < len) {
  170.         c = *p;
  171.  
  172.         switch (VRstate) {
  173.             case DONE:
  174.                 if (c == ESC)
  175.                     VRstate = ESCFOUND;
  176.                 else
  177.                     return count;
  178.                 break;
  179.  
  180.             case ESCFOUND:
  181.                 if (c == CMDTRM)
  182.                     VRstate = WANTCMD;
  183.                 else {
  184.                     VRstate = DONE;
  185.                     return count;
  186.                 }
  187.                 break;
  188.  
  189.             /*    looking for a valid command char */
  190.             case WANTCMD:
  191.                 for (i = 0; i < NCMDS; i++) {
  192.                     if (cmdtab[i].c_name == c)
  193.                         break;
  194.                     }
  195.  
  196.                 VRcmdnum = i;
  197.  
  198.                 if (VRcmdnum == NCMDS) {
  199.                     VRstate = DONE;
  200.                     return 0;
  201.                     }
  202.  
  203.                 /*    set up for this command */
  204.                 VRargcount = 0;
  205.                 VRbufpos = 0;
  206.  
  207.                 VRstate = WANTDEL;
  208.                 break;
  209.  
  210.             /*    look for that first ; */
  211.             case WANTDEL:
  212.                 if (c == DELIM)
  213.                     VRstate = VRnextargstate(VRargcount, VRcmdnum);
  214.                 else
  215.                     VRstate = DONE;
  216.                 break;
  217.  
  218.             /*    looking for an integer arg */
  219.             case IARG:
  220.                 switch (c) {
  221.  
  222.                     /*    we've found the end of the argument, so
  223.                         try to put into the vector for later use */
  224.                     case DELIM:
  225.                     case CMDTRM:
  226.                         VRtempdata[VRbufpos] = '\0';
  227.  
  228.                         /*    copy into argument union */
  229.                         (void)sscanf(VRtempdata,"%d",&VRargs[VRargcount].a_num);
  230.                         VRbufpos = 0;
  231.  
  232.                         VRargcount++;
  233.                         if (c == DELIM)
  234.                             VRstate = VRnextargstate(VRargcount, VRcmdnum);
  235.                         else
  236.                             if (cmdtab[VRcmdnum].c_flags & FL_DATA)
  237.                                 VRstate = DATA;
  238.                             else {    /*    run the command */
  239.                                 (*cmdtab[VRcmdnum].c_func)(VRargs, (char *)0L);
  240.                                 VRstate = DONE;
  241.                             }
  242.                         break;
  243.  
  244.                     /*    copy over characters for later */
  245.                     default:
  246.                         VRtempdata[VRbufpos++] = c;
  247.                 }
  248.                 break;
  249.  
  250.             /*    looking for string arg */
  251.             case SARG:
  252.                 switch (c) {
  253.                     /*    put string into argument vector */
  254.                     case DELIM:
  255.                     case CMDTRM:
  256.                         
  257.                         VRtempdata[VRbufpos] = '\0';
  258. /*
  259.                         VRargs[VRargcount].a_ptr = NewPtr((unsigned)VRbufpos+1);
  260.                         
  261.                         if (VRargs[VRargcount].a_ptr == (char *)0L) {
  262.                             VRstate = DONE;
  263.                             break;
  264.                         }
  265. */
  266.  
  267.                         (void)strcpy(VRargs[VRargcount].a_ptr, VRtempdata);
  268.                         VRbufpos = 0;
  269.                         VRargcount++;
  270.                         if (c == DELIM)
  271.                             VRstate = VRnextargstate(VRargcount, VRcmdnum);
  272.                         else
  273.                             if (cmdtab[VRcmdnum].c_flags & FL_DATA)
  274.                                 VRstate = DATA;
  275.                             else {    /*    run the command */
  276.                                 (*cmdtab[VRcmdnum].c_func)(VRargs, (char *)0L);
  277.                                 VRstate = DONE;
  278.                             }
  279.                         break;
  280.  
  281.                     /*    save string for later */
  282.                     default:
  283.                         VRtempdata[VRbufpos++] = c;
  284.                 }
  285.                 break;
  286.  
  287.             /*    looking for a count argument */
  288.             case CARG:
  289.                 switch (c) {
  290.                     /*    we've found the end of the argument, so
  291.                         try to put into the vector for later use */
  292.                     case DELIM:
  293.                     case CMDTRM:
  294.                         VRtempdata[VRbufpos] = '\0';
  295.  
  296.                         /*    copy into argument union */
  297.                         (void)sscanf(VRtempdata,"%d",&VRdatalen);
  298.                         (void)sscanf(VRtempdata,"%d",&VRargs[VRargcount].a_num);
  299.  
  300.                         if (VRdatalen > LINEMAX)
  301.                             VRdatalen = LINEMAX;
  302.                         VRargcount++;
  303.                         VRbufpos = 0;
  304.  
  305.                         if (c == DELIM)
  306.                             VRstate = VRnextargstate(VRargcount, VRcmdnum);
  307.                         else
  308.                             if (cmdtab[VRcmdnum].c_flags & FL_DATA)
  309.                                 VRstate = DATA;
  310.                             else {    /*    run the command */
  311.                                 (*cmdtab[VRcmdnum].c_func)(VRargs, (char *)0L);
  312.                                 VRstate = DONE;
  313.                             }
  314.  
  315.                         /*    allocate storage for data */
  316.                         VRptr = VRspace;
  317.  
  318.                         if (VRptr == (char *)0L) {
  319.                             VRstate = DONE;
  320.                             return 0;
  321.                             }
  322.     
  323.                         VRptr2 = VRptr;
  324.                         decode0();            /* reset decoder */
  325.                         break;
  326.  
  327.                     /*    copy over characters for later */
  328.                     default:
  329.                         VRtempdata[VRbufpos++] = c;
  330.                 }
  331.                 break;
  332.  
  333.             /*    retrieve a line of data */
  334.             case DATA:
  335.                 /*    store bytes until done */
  336.                 if (0 <= (i = decode1(c))) {
  337.                     *VRptr2++ = i;
  338.                     --VRdatalen;
  339.                     }
  340.  
  341.                 if (!VRdatalen) {    /*    we've got all of the data */
  342.                     (*cmdtab[VRcmdnum].c_func)(VRargs, VRptr);
  343.                     VRstate = DONE;
  344.                     }
  345.                 break;
  346.  
  347.         } /* end switch(VRstate)*/
  348.  
  349.         p++;
  350.         count++;
  351.     } /* end while loop */
  352.  
  353.     return count;
  354. }
  355.  
  356. /*
  357. ** VRnextargstate -- return the next state based on where we're
  358. **                  -- at already.
  359. **
  360. ** Arguments:
  361. **
  362. ** short ac         -- current argument count
  363. ** short state       -- current state
  364. ** short c          -- current command
  365. **
  366. ** Returns:
  367. **
  368. ** short             -- next state to move to
  369. **
  370. */
  371.  
  372. static short VRnextargstate(short ac, short c)
  373. {
  374.  
  375.     switch (cmdtab[c].c_args[ac]) {
  376.         case INT:
  377.             return IARG;
  378.         case STRING:
  379.             return SARG;
  380.         case COUNT:
  381.             return CARG;
  382.         case 0:
  383.             return DATA;
  384.  
  385.         /*    in case of error*/
  386.         default:
  387.             return DONE;
  388.     }
  389. }
  390.  
  391. /*
  392. ** VRwindow -- create a new raster window
  393. **
  394. ** Arguments:
  395. **
  396. **    union arg av[];    -- the argument vector
  397. **
  398. **    short        av[0, 1];     -- upper left;
  399. **    short        av[2, 3];     -- width, height
  400. **    short        av[4];         -- window hardware display number
  401. **    char    *av[5];       -- title
  402. **
  403. ** Returns:
  404. **
  405. **    None.  No provision has been made for error returns in any of
  406. **    these routines because I don't know what to do if an error
  407. **    occurs.  Perhaps a better man than I can figure out how to 
  408. **    deal with this.
  409. **    N.B -- these functions are declared as short, in the event
  410. **    that an error return is added.
  411. */
  412.  
  413. short    VRwindow(union arg av[], char *unused)
  414. {
  415.     #pragma unused (unused)
  416.     VRW    *w = VRhead.w_next;
  417.     short    ret;
  418.     
  419.     /*    search list, and if needed, NewPtr some space for a new window thing */
  420.  
  421.     while (w) {
  422.         if (!strcmp(w->w_name,av[5].a_ptr)
  423.             && w->w_width == av[2].a_num 
  424.             && w->w_height == av[3].a_num)        /* don't re-allocate win */
  425.             return(1);
  426.         if (!strcmp(w->w_name,av[5].a_ptr))        /* duplicate, different size */
  427.             w->w_used = 1;
  428.         w = w->w_next;
  429.     }
  430.  
  431.     w = (VRW *)NewPtr(sizeof(VRW));                /* new element for list */
  432.     if (!w)
  433.         return(-1);
  434.         
  435.     w->w_next = VRhead.w_next;                    /* set next equal to current head */
  436.     VRhead.w_next = w;                            /* set head of list equal to me */
  437.     
  438.     /*
  439.     ** fill in the new window area
  440.     */
  441.  
  442.     w->w_left = av[0].a_num;
  443.     w->w_top = av[1].a_num;
  444.     w->w_width = av[2].a_num;
  445.     w->w_height = av[3].a_num;
  446.     w->w_display = av[4].a_num;
  447.     w->w_used = 0;
  448.     strncpy(w->w_name,av[5].a_ptr,100);
  449.  
  450.     if (w->w_width > LINEMAX)            /* have to be SOME limits */
  451.         w->w_width = LINEMAX;
  452.  
  453.     if (0 <= (ret = MacRGnewwindow( w->w_name, w->w_left, w->w_top,
  454.                     w->w_left+w->w_width, w->w_top+w->w_height )))
  455.         MacRGsetwindow( ret);
  456.  
  457.     w->w_rr.wn = ret;
  458.  
  459.     return(ret);
  460. }
  461.  
  462. /*
  463. ** VRdestroy -- destroy a window by name
  464. **
  465. ** Arguments:
  466. **
  467. **   union arg av[]; -- the argument vector
  468. **
  469. **   char *av[0] -- the name of the window
  470. **
  471. ** Returns:
  472. **
  473. **   None.
  474. **
  475. */
  476.  
  477. short    VRdestroy(union arg av[], char *unused)
  478. {
  479.     #pragma unused (unused)
  480.     VRW        *w,*ow;
  481.  
  482.     ow = &VRhead;
  483.     w = ow->w_next;
  484.  
  485.     while (w) {
  486.         if (!strcmp(w->w_name, av[0].a_ptr) ) {
  487.             MacRGremove( w->w_rr.wn);
  488.             ow->w_next = w->w_next;
  489.             DisposPtr((char *)w);
  490.         }
  491.         else
  492.             ow = ow->w_next;
  493.  
  494.         w = ow->w_next;
  495.     }
  496.  
  497.     return 0;
  498. }
  499.  
  500. void    VRdestroybyName(char *name)
  501. {
  502.     union arg blah;
  503.     
  504.     strncpy(blah.a_ptr, name, 100);
  505.     VRdestroy(&blah, NULL);
  506. }
  507.  
  508. /*
  509. ** VRmap -- take a color map command and set the palette
  510. **
  511. ** Arguments:
  512. **
  513. **   union arg av[]; -- the argument vector
  514. **
  515. **   short     av[0, 1];  -- start & length of map segment
  516. **     short    av[2];     -- count of data needed (info only)
  517. **     char    *av[3];    -- window name
  518. **   char    *data;     -- pointer to the data  
  519. **
  520. ** Returns:
  521. **
  522. **   None.
  523. **
  524. */
  525.  
  526. short    VRmap(union arg av[], char *data)
  527. {
  528.     VRW            *w;
  529.  
  530.     w = VRlookup(av[3].a_ptr);
  531.  
  532.     if (!w)
  533.         return 0;
  534.  
  535.     MacRGmap(av[0].a_num, av[1].a_num, data);
  536. }
  537.  
  538. /*
  539. ** VRpixel -- display a line of pixel data
  540. ** 
  541. ** Arugments:
  542. **
  543. **    union arg av[]; -- the argument vector
  544. **
  545. **    short        av[0];  -- x coordinate
  546. **    short         av[1];  -- y coordinate
  547. **  short     av[2];  -- pixel expansion factor
  548. **    short         av[3];  -- length of data
  549. **    char    *av[4]; -- window name
  550. **    char    *data;  -- pointer to data
  551. **
  552. ** Returns:
  553. **
  554. **    None.
  555. **
  556. */
  557.  
  558. short    VRpixel(union arg av[], char *data)
  559. {
  560.     VRW        *w;
  561.     short    i,lim;
  562.     char    *p,*q;
  563.  
  564.     /*    find the right window */
  565.     w = VRlookup(av[4].a_ptr);
  566.  
  567.     if (w == (VRW *)0L)
  568.         return 0;
  569.  
  570.     lim = av[3].a_num*av[2].a_num;        /* total number of expanded pixels */
  571.     if (lim > w->w_width)
  572.         lim = w->w_width;
  573.  
  574.     if (av[2].a_num > 1) {
  575.         p = data;
  576.         q = VRsp2;
  577.         for (i=0; i < lim; i++) {
  578.             *q++ = *p;
  579.             if (!((i+1) % av[2].a_num))
  580.                 p++;
  581.         }
  582.         for (i=0; i<av[2].a_num; i++)
  583.             MacRGraster( VRsp2, av[0].a_num, av[1].a_num+i,
  584.                              av[0].a_num+lim, av[1].a_num+i,lim);
  585.  
  586.     }
  587.     else
  588.         return     MacRGraster( data, av[0].a_num, av[1].a_num,
  589.                     av[0].a_num+av[3].a_num, av[1].a_num,lim);
  590.  
  591.     return 0;
  592. }
  593.  
  594. /*
  595. ** VRimp -- display a line of IMPCOMP encoded data
  596. **   One line of IMPCOMP data gives 4 lines output.
  597. ** 
  598. ** Arugments:
  599. **
  600. **    union arg av[]; -- the argument vector
  601. **
  602. **    short        av[0];  -- x coordinate
  603. **    short         av[1];  -- y coordinate
  604. **  short     av[2];  -- pixel expansion
  605. **    short         av[3];  -- length of data
  606. **    char    *av[4]; -- window name
  607. **    char    *data;  -- pointer to data
  608. **
  609. ** Returns:
  610. **
  611. **    None.
  612. **
  613. */
  614.  
  615. short    VRimp(union arg av[], char *data)
  616. {
  617.     VRW        *w;
  618.     short    i,lim,j;
  619.     char    *p,*q;
  620.  
  621.     /*    find the right window */
  622.     w = VRlookup(av[4].a_ptr);
  623.  
  624.     if (w == (VRW *)0L)
  625.         return 0;
  626.  
  627.     unimcomp((unsigned char *) data,(unsigned char *) VRsp2,av[3].a_num,w->w_width);   /* BYU LSC - decompress it */
  628.     /* gives four lines in the VRsp2 buffer, now pixel expand */
  629.  
  630.     i = av[3].a_num;
  631.  
  632.     lim = i*av[2].a_num;        /* total number of expanded pixels on a line*/
  633.     if (lim > w->w_width)
  634.         lim = w->w_width;
  635.     if (i > w->w_width)
  636.         i = w->w_width;
  637.  
  638.     p = VRsp2;                                /* from this buffer */
  639.     for (j=0; j<4; j++) {
  640.         if (av[2].a_num > 1) {
  641.             q = VRspace;                    /* to here */
  642.             for (i=0; i < lim; i++) {
  643.                 *q++ = *p;
  644.                 if (!((i+1) % av[2].a_num))
  645.                     p++;
  646.             }
  647.             p++;
  648.             for (i=0; i<av[2].a_num; i++)
  649.                 MacRGraster(VRspace, av[0].a_num, av[1].a_num+i+j*av[2].a_num,
  650.                     av[0].a_num + av[3].a_num,    av[1].a_num+i+j*av[2].a_num, lim );
  651.  
  652.         }
  653.         else {
  654.             MacRGraster(p, av[0].a_num,        av[1].a_num+j,
  655.                     av[0].a_num + av[3].a_num, av[1].a_num+j, i);
  656.             p += av[3].a_num;            /* increment to next line */
  657.         }
  658.  
  659.     }
  660.  
  661.     return 0;
  662. }
  663.  
  664. /************************************************************************/
  665. /*  Function    : unimcomp                        */
  666. /*  Purpose    : 'Decompresses' the compressed image            */
  667. /*  Parameter    :                            */
  668. /*    xdim       - x dimensions of image                */
  669. /*    lines      - number of lines of compressed image                  */
  670. /*    in, out    - Input buffer and output buffer. Size of input buffer */
  671. /*           is xdim*lines. Size of output buffer is 4 times      */
  672. /*           that. It 'restores' images into seq-type files       */
  673. /*  Returns      : none                            */
  674. /*  Called by   : External routines                    */
  675. /*  Calls       : none                            */
  676. /************************************************************************/
  677.  
  678. void unimcomp(unsigned char in[], unsigned char out[], short xdim, short xmax)
  679. {
  680.   short                bitmap, temp, lines=1;
  681.   register short     i, j, k, x;
  682.   unsigned char        hi_color, lo_color;
  683.  
  684.     if (xmax < xdim)        /* don't go over */
  685.         xdim = xmax;
  686.  
  687.   /* go over the compressed image */
  688.     for (x=0; x<xdim; x=x+4)
  689.     {
  690.       k = x;
  691.       hi_color = in[k+2]; 
  692.       lo_color = in[k+3];
  693.  
  694.       bitmap = (in[k] << 8) | in[k+1];
  695.  
  696.       /* store in out buffer */
  697.       for (i=0; i<4; i++)
  698.       {
  699.         temp = bitmap >> (3 - i)*4;
  700.         for (j=x; j<(x+4); j++)
  701.         {
  702.        if ((temp & 8) == 8)
  703.         out[i*xdim+j] = hi_color;
  704.       else
  705.         out[i*xdim+j] = lo_color;
  706.       temp = temp << 1;
  707.     }
  708.       }
  709.     } /* end of for x */
  710. } /* end of unimcomp */
  711.  
  712. /*  unrleit - Decompress run length encoding. */
  713. short    unrleit(unsigned char *buf, unsigned char *bufto, short inlen, short outlen)
  714. {
  715.     register short            cnt;
  716.     register unsigned char    *p,*q;
  717.     unsigned char            *endp,*endq;
  718.     
  719.     p = buf;
  720.     endp = buf + inlen;
  721.     q = bufto;
  722.     endq = bufto + outlen;
  723.     while (p < endp && q < endq) {    /* go 'til p or q hits end */
  724.         cnt = *p++;                    /* count field */
  725.         if (!(cnt & 128)) {            /* is set of uniques */
  726.             while (cnt-- && q < endq)
  727.                 *q++ = *p++;        /* copy unmodified */
  728.             }
  729.         else {
  730.             cnt &= 127;                /* strip high bit */
  731.             while (cnt-- && q < endq)
  732.                 *q++ = *p;            /* copy same character */
  733.             p++;                    /* skip that character */
  734.         }
  735.     } /* while */
  736.  
  737.     return((short)(q-bufto));
  738. }
  739.  
  740. /***************************************************************************/
  741. /*
  742. ** VRrle -- display a line of run-length encoded data
  743. ** 
  744. ** Arugments:
  745. **
  746. **    union arg av[]; -- the argument vector
  747. **
  748. **    short        av[0];  -- x coordinate
  749. **    short         av[1];  -- y coordinate
  750. **  short     av[2];  -- pixel expansion
  751. **    short         av[3];  -- length of data
  752. **    char    *av[4]; -- window name
  753. **    char    *data;  -- pointer to data
  754. **
  755. ** Returns:
  756. **
  757. **    None.
  758. **
  759. */
  760. short    VRrle(union arg av[], char *data)
  761. {
  762.     VRW     *w;
  763.     short    i,lim;
  764.     char    *p,*q;
  765.  
  766.     /*    find the right window */
  767.  
  768.     w = VRlookup(av[4].a_ptr);
  769.  
  770.     if (w == (VRW *)0L)
  771.         return 0;
  772.  
  773.     i = unrleit((unsigned char *) data,(unsigned char *) VRsp2,av[3].a_num,w->w_width);   /* BYU LSC - decompress it */
  774.  
  775.  
  776.     lim = i*av[2].a_num;                /* total number of expanded pixels */
  777.     if (lim > w->w_width)
  778.         lim = w->w_width;
  779.  
  780.     if (av[2].a_num > 1) {
  781.         p = VRsp2;                        /* from this buffer */
  782.         q = VRspace;                    /* to here */
  783.         for (i=0; i < lim; i++) {
  784.             *q++ = *p;
  785.             if (!((i+1) % av[2].a_num))
  786.                 p++;
  787.         }
  788.         for (i=0; i<av[2].a_num; i++)
  789.             MacRGraster( VRspace, av[0].a_num, av[1].a_num+i,
  790.                              av[0].a_num+lim, av[1].a_num+i,lim);
  791.  
  792.     }
  793.     else
  794.         return     MacRGraster( VRsp2, av[0].a_num, av[1].a_num,
  795.                     av[0].a_num+i, av[1].a_num,i);
  796.  
  797.     return 0;
  798.  
  799. }
  800.  
  801. /*
  802. ** VRfile    -- cause the named window to be dumped to a file
  803. **
  804. ** Arguments:
  805. **
  806. **    union arg av[];        -- the argument vector
  807. **
  808. **    short        av[0];        -- start x coordinate
  809. **    short        av[1];        -- start y coordinate
  810. **    short        av[2];        -- width of region to dump
  811. **    short        av[3];        -- height of region to dump
  812. **    short        av[4];        -- format of file -- machine dependent
  813. **    char    *av[5];        -- file name to use
  814. **    char    *av[6];        -- window name to dump
  815. **
  816. ** Returns:
  817. **
  818. **    short;                -- 1 if success, 0 if failure
  819. **
  820. */
  821.  
  822. short    VRfile(union arg av[], char *unused)
  823. {
  824. #ifdef IMPLEMENTED
  825.     #pragma unused (unused)
  826.     VRW    *w;
  827.  
  828.     /*    Look up the window */
  829.  
  830.     w = VRlookup(av[6].a_ptr);
  831.  
  832.     if (w == (VRW *)0L)
  833.         return 0;
  834.  
  835.     /*    call the low level file routine */
  836.  
  837.     return RRfile(w, av[0].a_num, av[1].a_num, av[2].a_num, av[3].a_num,
  838.         av[4].a_num, av[5].a_ptr);
  839. #else 
  840. #pragma unused(av, unused)
  841.     return 0;
  842. #endif IMPLEMENTED
  843. }
  844.  
  845. /*
  846. ** VRclick    -- Click the Slide Camera -- very machine dependent
  847. **
  848. ** Arguments:
  849. **
  850. **    union arg    av[];        -- the argument vector
  851. **
  852. **    char    *av[0];            -- window name
  853. **
  854. ** Returns:
  855. **
  856. **    short;                    -- 1 if success, 0 if failure
  857. */
  858.  
  859. short    VRclick(union arg av[], char *unused)
  860. {
  861. #ifdef IMPLEMENTED
  862.     #pragma unused (unused)
  863.     VRW    *w;
  864.  
  865.     /*    look up the window */
  866.  
  867.     w = VRlookup(av[0].a_ptr);
  868.  
  869.     if (w == (VRW *)0L)
  870.         return 0;
  871.  
  872.     return RRclick(w);
  873. #else 
  874. #pragma unused(av, unused)
  875.     return 0;
  876. #endif IMPLEMENTED
  877. }
  878.  
  879. /*
  880. ** VRmsave    -- Save the named colormap to the file -- saves the whole thing
  881. **
  882. ** Arguments:
  883. **
  884. **    union arg    av[];        -- the argument vector
  885. **
  886. **    char    *av[0];            -- file name
  887. **    char    *av[1];            -- window name
  888. **
  889. ** Returns:
  890. **
  891. **    short;                    -- 1 if success, 0 if failure
  892. */
  893.  
  894. short    VRmsave(union arg av[], char *unused)
  895. {
  896. #ifdef IMPLEMENTED
  897.     #pragma unused (unused)
  898.     VRW    *w;
  899.  
  900.     /*    look up the window */
  901.     w = VRlookup(av[1].a_ptr);
  902.  
  903.     if (w == (VRW *)0L)
  904.         return 0;
  905.  
  906.     return RRmsave(w, av[0].a_ptr);
  907. #else 
  908. #pragma unused(av, unused)
  909.     return 0;
  910. #endif IMPLEMENTED
  911. }
  912.  
  913. /*
  914. ** VRlookup            -- find an entry in the list by name
  915. **
  916. ** Arguments:
  917. **
  918. **    char    *name;    -- the name of the window
  919. **
  920. ** Returns:
  921. **
  922. **    VRW    *w;            -- pointer to window structure, (VRW *)0 if not found
  923. **
  924. */
  925.  
  926. VRW    *VRlookup(char *name)
  927. {
  928.     VRW    *w = VRhead.w_next;
  929.  
  930.     while (w) {
  931.         if (!strcmp(w->w_name, name) && !w->w_used) {    /* same name, not old dup */
  932.             if (w->w_rr.wn < 0)                            /* maybe window don't work */
  933.                 return(NULL);
  934.             MacRGsetwindow(w->w_rr.wn);
  935.             return(w);
  936.             }
  937.         w = w->w_next;
  938.     }
  939.  
  940.     return(NULL);
  941. }
  942.  
  943. /*
  944. ** VRcleanup -- remove all windows from the screen
  945. **
  946. ** Arguments:
  947. **
  948. **    None.
  949. **
  950. ** Returns:
  951. **
  952. **    short;    1    -- always successful, or there's nothing you can do
  953. **                -- about it anyways...
  954. **
  955. */
  956.  
  957. short    VRcleanup(void)
  958. {
  959.     VRW *w = VRhead.w_next;
  960.     VRW *x;
  961.  
  962.     while (w != (VRW *)0L) {
  963.         x = w->w_next;
  964.         MacRGremove( w->w_rr.wn);
  965.         w = x;
  966.     }
  967.  
  968.     return 1;
  969. }
  970.  
  971. /************************************************************************/
  972. /*  decoding
  973. *   handle the special ASCII printable character encoding of data bytes.
  974. */
  975.  
  976. /***********************************************************************/
  977. /*
  978. *  123 precedes #'s 0-63 
  979. *  124 precedes #'s 64-127
  980. *  125 precedes #'s 128-191
  981. *  126 precedes #'s 192-255
  982. *  overall:  realchar = (specialchar - 123)*64 + (char-32) 
  983. *            specialchar = r div 64 + 123
  984. *            char = r mod 64 + 32
  985. */
  986. /***********************************************************************/
  987. static short dstate=FRSKIP,dspec=0;
  988.  
  989. /*    set up receive */
  990. void    decode0(void)
  991. {
  992.     dstate = FRIN;
  993. }
  994.  
  995. short    decode1(char c)
  996. {
  997.     switch (dstate) {
  998.         case FRSKIP:
  999.             return(-1);
  1000.     
  1001.         case FRIN:                        /* decoding */
  1002.             if (c > 31 && c < 123)
  1003.                 return(c);
  1004.             else {
  1005.                 dspec = c;                /* save special character */
  1006.                 dstate = FRSPECIAL;        /* doing special character */
  1007.             }
  1008.             return(-1);
  1009.             
  1010.         case FRSPECIAL:
  1011.             switch (dspec) {
  1012.                 case 123:
  1013.                 case 124:
  1014.                 case 125:
  1015.                 case 126:            /* encoded character */
  1016.                     dstate = FRIN;
  1017.                     return(((dspec - 123)<< 6) - 32 + c);
  1018.                     
  1019.                 default:            /* mistaken character in stream */
  1020.                     dstate = FRIN;  /* assume not special */
  1021.                     return(decode1(c));  /* check for sure */
  1022.                     break;
  1023.                 }
  1024.         break;
  1025.     } // switch (dstate)
  1026. }
  1027.